package com.projet.whattowatch.objet;

import android.content.Context;
import android.util.Log;
import android.widget.Toast;

import java.util.ArrayList;

public class Utilisateur implements Comparable<Utilisateur>
{
	private String nom;
	private String prenom;
	private String adresseMail;
	private int dateDeNaissance;
	private ArrayList<Humain> listActeurFav;
	private ArrayList<String> listGenreFav;
	private ArrayList<Humain> listRealisateurFav;
	private ArrayList<Film> listFilmAVoir;
	private String motDePasse;
	private String sex;

	/**
	 * Constructor for objects of class Utilisateur
	 */

	public Utilisateur(String nom, String prenom, String adresseMail, String sex, String motDePasse, 
						ArrayList<Humain> listActeurFav, ArrayList<Humain> listRealisateurFav, 
						ArrayList<String> listGenreFav, ArrayList<Film> listFilmAVoir, int age) {
		this.nom = nom;
		this.prenom = prenom;
		this.adresseMail = adresseMail;
		this.dateDeNaissance = 2014-age;
		this.listActeurFav = listActeurFav;
		this.listGenreFav = listGenreFav;
		this.listRealisateurFav = listRealisateurFav;
		this.listFilmAVoir = listFilmAVoir;
		this.motDePasse = motDePasse;
		this.sex = sex; // on est oblige de choisir l'un ou l'autre je pense

	}

	public String getNom() {
		return this.nom;
	}

	public String getPrenom() {
		return this.prenom;
	}

	public int getDateDeNaissance() {
		return this.dateDeNaissance;
	}

	public String getMotDePasse() {
		return this.motDePasse;
	}

	public String getSex() {
		return this.sex;
	}

	public ArrayList<Film> getListFilmAVoir() {
		return this.listFilmAVoir;
	}

	public ArrayList<Humain> getListActeurFav() {
		return this.listActeurFav;
	}

	public ArrayList<Humain> getListRealisateurFav() {
		return this.listRealisateurFav;
	}

	public void setNom(String monNom) {
		this.nom = monNom;
	}

	public void setPrenom(String monPrenom) {
		this.prenom = monPrenom;
	}

	public void setDateDeNaissance(int maDateDeNaissance) {
		this.dateDeNaissance = maDateDeNaissance;
	}

	public void setSex(String monSex) {
		this.sex = monSex;
	}

	public void changePassword(String monMotDePasse, String oldMotDePasse) {
		if (oldMotDePasse.equals(this.getPassword()))
		{
		this.motDePasse = monMotDePasse;
		}
	}

	public String getPassword() {
		return this.motDePasse;
	}
	
	public ArrayList<String> getListGenreFav() {
		return listGenreFav;
	}

	public void setListGenreFav(ArrayList<String> listGenreFav) {
		this.listGenreFav = listGenreFav;
	}

	/**
	 * Add the realisateur specified in the parameter, at the end of the
	 * ListRealisateurFav
	 */
	public void addRealisateurFav(Humain monRealisateur) {
		boolean alreadyIn = false;
		for (int i = 0; i < this.listRealisateurFav.size(); i++) {
			if (monRealisateur.compareTo(this.listRealisateurFav.get(i)) == 0 )
			{
				alreadyIn= true;
			}
		}
		
		if(!alreadyIn) this.listRealisateurFav.add(monRealisateur);
		
	}
	

	/**
	 * return true if he removed succefully the Element in parameter, false
	 * otherwise
	 */
	public boolean removeRealisateurFav(Humain monRealisateur) {
		for (int i = 0; i < this.listRealisateurFav.size(); i++) 
		{
			if(monRealisateur.compareTo(listRealisateurFav.get(i)) == 0 )
			{
				listRealisateurFav.remove(i);
				return true;
			}
			
		}
		return false;
	}

	public String getAdresseMail() {
		return adresseMail;
	}

	public void setAdresseMail(String adresseMail) {
		this.adresseMail = adresseMail;
	}

	/**
	 * Add the Acteur specified in the parameter, at the end of the
	 * ListActeurFav
	 */
	public void addActeurFav(Humain monActeur) {
		boolean alreadyIn = false;
		for (int i = 0; i < this.listActeurFav.size(); i++) {
			if (monActeur.compareTo(this.listActeurFav.get(i)) == 0 )
			{
				alreadyIn= true;
			}
		}
		
		if(!alreadyIn) this.listActeurFav.add(monActeur);
		
	}

	/**
	 * return true if he removed succefully the Element in parameter, false
	 * otherwise
	 */
	public boolean removeActeurFav(Humain monActeur) 
	{
		for (int i = 0; i < this.listActeurFav.size(); i++) 
		{
			if(monActeur.compareTo(listActeurFav.get(i)) == 0 )
			{
				listActeurFav.remove(i);
				return true;
			}
			
		}
		return false;
	}
		

	/**
	 * Add the Genre specified in the parameter, at the end of the ListGenreFav
	 */
	public void addGenreFav(String monGenre)
	{
		boolean alreadyIn = false;
		for (int i = 0; i < this.listGenreFav.size(); i++) {
			if (monGenre.compareTo(this.listGenreFav.get(i)) == 0 )
			{
				alreadyIn= true;
			}
		}
		
		if(!alreadyIn) this.listGenreFav.add(monGenre);
		
	}

	@Override
	public int compareTo(Utilisateur user)
	{
		return this.adresseMail.compareTo(user.getAdresseMail());
	}

	/**
	 * return true if he removed succefully the Element in parameter, false
	 * otherwise
	 */
	public boolean removeGenreFav(String monGenre) 
	{
		for (int i = 0; i < this.listGenreFav.size(); i++) 
		{
			if(monGenre.compareTo(listGenreFav.get(i)) == 0 )
			{
				listGenreFav.remove(i);
				return true;
			}
			
		}
		return false;
	}

	/**
	 * Add the Film specified in the parameter, at the end of the ListFilmAVoir
	 */
	public void addFilmAVoir(Film monFilm) {
		boolean alreadyIn = false;
		for (int i = 0; i < this.listFilmAVoir.size(); i++) {
			if (monFilm.compareTo(this.listFilmAVoir.get(i)) == 0 )
			{
				alreadyIn= true;
			}
		}
		
		if(!alreadyIn) this.listFilmAVoir.add(monFilm);
	}

	/**
	 * return true if he removed succefully the Element in parameter, false
	 * otherwise
	 */
	public boolean removeFilmAVoir(Film monFilm) {
		for (int i = 0; i < this.listFilmAVoir.size(); i++) {
			if(monFilm.compareTo(listFilmAVoir.get(i)) == 0 )
			{
				listFilmAVoir.remove(i);
			}
		}
		return true;
	}

	/**
	 */
	public ArrayList<Film> smartRequest(LibFilm maLibFilm) {
		ArrayList<SmartFilm> listSmartFilm = new ArrayList<SmartFilm>();

		// on parcourt la liste de film de la librairie
		for (int i = 0; i < maLibFilm.getListFilm().size(); i++) {
			// on cree le smartFilm associe au ieme film de la librairie
			SmartFilm monSmartfilm = new SmartFilm(maLibFilm.getFilm(i), 0);
			Film monFilm = monSmartfilm.getFilm();
			if (monFilm.getNom().equals("The Transporter")) 
			{
				Log.d("", "");
			}

			// decremente smartscore si l'utilisateur est nee apr�s la sorti du
			// film

			if (monFilm.getDate() < this.getDateDeNaissance()) {
				monSmartfilm.setSmartScore(monSmartfilm.getSmartScore() - 9);

			}

			// incremente smartscore si l'utilisateur aime les real. du film
			for (int j = 0; j < this.listRealisateurFav.size(); j++) {
				for (int k = 0; k < monFilm.getListRealisateur().size(); k++) {
					if (monFilm.getListRealisateur().get(k)
							.compareTo(this.listRealisateurFav.get(j)) == 0) {
						monSmartfilm
								.setSmartScore(monSmartfilm.getSmartScore() + 9);
					}
				}
			}

			// incremente smartscore si l'utilisateur aime les acteurs du film
			for (int j = 0; j < this.listActeurFav.size(); j++) {
				for (int k = 0; k < monFilm.getListActeur().size(); k++) {
					if (((Humain)monFilm.getListActeur().get(k).get(0))
							.compareTo(this.listActeurFav.get(j)) == 0) {
						monSmartfilm
								.setSmartScore(monSmartfilm.getSmartScore() + 3);
					}
				}
			}

			// incremente smartscore si l'utilisateur aime le genre du film
			for (int j = 0; j < this.listGenreFav.size(); j++) {
				for (int k = 0; k < monFilm.getListGenre().size(); k++)
				{
					if (monFilm.getListGenre().get(k).compareTo(this.listGenreFav.get(j)) == 0)
					{
						monSmartfilm.setSmartScore(monSmartfilm.getSmartScore() + 6);
					}
				}
			}

			// Augmente smartScore si il y a des points en communs avec les
			// films � voir
			for (int l = 0; l < this.getListFilmAVoir().size(); l++) {
				 Film FilmAVoir = this.getListFilmAVoir().get(l);
				 
				 // Cherche les genres en communs
				 for (int j = 0; j < FilmAVoir.getListGenre().size(); j++) {
						for (int k = 0; k < monFilm.getListGenre().size(); k++) {
							if (monFilm.getListGenre().get(k)
									.compareTo(FilmAVoir.getListGenre().get(j)) == 0) {
								monSmartfilm
										.setSmartScore(monSmartfilm.getSmartScore() + 2);
							}
						}

					}
				 
				 // Cherche les Acteurs en communs
				 for (int j = 0; j < FilmAVoir.getListActeur().size(); j++) {
						for (int k = 0; k < monFilm.getListActeur().size(); k++) {
							if (((Humain)monFilm.getListActeur().get(k).get(0))
									.compareTo(((Humain)FilmAVoir.getListActeur().get(j).get(0))) == 0) {
								monSmartfilm
										.setSmartScore(monSmartfilm.getSmartScore() + 1);
							}
						}

					}
				 
				 // Cherche les Realisateurs en communs
				 for (int j = 0; j < FilmAVoir.getListRealisateur().size(); j++) {
						for (int k = 0; k < monFilm.getListRealisateur().size(); k++) {
							if (monFilm.getListRealisateur().get(k)
									.compareTo(FilmAVoir.getListRealisateur().get(j)) == 0) {
								monSmartfilm
										.setSmartScore(monSmartfilm.getSmartScore() + 3);
							}
						}

					}
				
			}

			// Ne prend pas en compte les films que l'utilisateur veut deja voir
			boolean check = true;
			for (int j = 0; j < this.getListFilmAVoir().size(); j++) {
				if (this.getListFilmAVoir().get(j).compareTo(monFilm) == 0)
					check = false;
			}
			if (!check)
				monSmartfilm.setSmartScore(Integer.MIN_VALUE);
			listSmartFilm.add(monSmartfilm);
		}

		Object newListSmartFilm[][] = new Object[listSmartFilm.size()][2];
		for (int a = 0; a < newListSmartFilm.length; a++) {
			
			newListSmartFilm[a][0] = listSmartFilm.get(a).getFilm();
			newListSmartFilm[a][1] = listSmartFilm.get(a).getSmartScore();
		}

		Object listSorted[][] = mergeSort(newListSmartFilm);
		ArrayList<Film> finalArray = new ArrayList<Film>();
		for (int a = 0; a < listSorted.length; a++) {
			Film finalFilm = (Film) listSorted[a][0];
			finalArray.add(finalFilm);
			Log.d("SmartRequest", finalFilm.getNom() + " : " + listSorted[a][1]);
		}
		return finalArray;
	}

	public static Object[][] mergeSort(Object[][] array) {
		if (array.length > 1) {
			// split array into two halves
			Object[][] left = leftHalf(array);
			Object[][] right = rightHalf(array);

			// recursively sort the two halves
			mergeSort(left);
			mergeSort(right);

			// merge the sorted halves into a sorted whole
			merge(array, left, right);
		}
		return array;
	}

	// Returns the first half of the given array.
	public static Object[][] leftHalf(Object[][] array) {
		int size1 = array.length / 2;
		Object[][] left = new Object[size1][2];

		for (int i = 0; i < size1; i++) {
			left[i] = array[i];
		}
		return left;
	}

	// Returns the second half of the given array.
	public static Object[][] rightHalf(Object[][] array) {
		int size1 = array.length / 2;
		int size2 = array.length - size1;
		Object[][] right = new Object[size2][2];

		for (int i = 0; i < size2; i++) {
			int newSize = i + size1;
			right[i] = array[newSize];
		}
		return right;
	}

	// Merges the given left and right arrays into the given
	// result array. Second, working version.
	// pre : result is empty; left/right are sorted
	// post: result contains result of merging sorted lists;
	public static void merge(Object[][] result, Object[][] left,
			Object[][] right) {
		int i1 = 0; // index into left array
		int i2 = 0; // index into right array

		for (int i = 0; i < result.length; i++) {
			if (i2 >= right.length
					|| (i1 < left.length && ((Integer) left[i1][1])
							.compareTo((Integer) right[i2][1]) <= 0)) {
				result[i] = left[i1]; // take from left
				i1++;
			} else {
				result[i] = right[i2]; // take from right
				i2++;
			}
		}
	}

	public void changeMotDePasse(String ancienMotDePasse,
			String nouveauMotDePasse, String confirmationMotDePasse,
			Context mContext) {
		if (this.motDePasse.equals(ancienMotDePasse)) {
			if (nouveauMotDePasse.equals(confirmationMotDePasse))
				this.motDePasse = nouveauMotDePasse;
			else
				afficheErreur(
						"Votre nouveau mot de passe et votre confirmation ne correspondent pas",
						mContext);
		} else
			afficheErreur("Votre ancien mot de passe est incorrect", mContext);
	}

	/**
	 * A compl�ter
	 */
	public void connectFacebook() {
		System.out.println("Connection a facebook");
	}

	// completer toutes les autres methodes

	public static void afficheErreur(String erreur, Context context) {
		Toast.makeText(context, erreur, Toast.LENGTH_SHORT).show();
	}

}
